package com.szcinda.service.dto.client;

import com.szcinda.repository.*;
import com.szcinda.service.PageResult;
import com.szcinda.service.SnowFlakeFactory;
import com.szcinda.service.TypeStringUtils;
import com.szcinda.service.dto.carrier.CarrierVehicleFeeImportDto;
import com.szcinda.service.dto.line.LineQueryDto;
import com.szcinda.service.dto.line.VehicleFeeQueryDto;
import com.szcinda.service.dto.linePrice.LinePriceService;
import com.szcinda.service.dto.log.LogCreateDto;
import com.szcinda.service.dto.log.LogService;
import com.szcinda.service.dto.organization.OrganizationService;
import com.szcinda.service.dto.role.RoleRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.time.Instant;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Transactional
public class ClientServiceImpl implements ClientService {

    private final ClientRepository clientRepository;
    private final SnowFlakeFactory snowFlakeFactory;
    private final ContractRepository contractRepository;
    private final RateRepository rateRepository;
    private final OrganizationService organizationService;
    private final RoleRepository roleRepository;
    private final LinePriceService linePriceService;
    private final OrderFeeRepository orderFeeRepository;
    private final UserRepository userRepository;
    private final FeeItemRepository feeItemRepository;
    private final LinePriceRepository linePriceRepository;
    private final BaoGuanFeeRepository baoGuanFeeRepository;
    private final ClientVehiclePriceRepository clientVehiclePriceRepository;
    private final VehicleRepository vehicleRepository;
    private final LogService logService;

    public ClientServiceImpl(ClientRepository clientRepository, ContractRepository contractRepository, RateRepository rateRepository, OrganizationService organizationService, RoleRepository roleRepository, LinePriceService linePriceService, OrderFeeRepository orderFeeRepository, UserRepository userRepository, FeeItemRepository feeItemRepository, LinePriceRepository linePriceRepository, BaoGuanFeeRepository baoGuanFeeRepository, ClientVehiclePriceRepository clientVehiclePriceRepository, VehicleRepository vehicleRepository, LogService logService) {
        this.clientRepository = clientRepository;
        this.contractRepository = contractRepository;
        this.rateRepository = rateRepository;
        this.organizationService = organizationService;
        this.roleRepository = roleRepository;
        this.linePriceService = linePriceService;
        this.orderFeeRepository = orderFeeRepository;
        this.userRepository = userRepository;
        this.feeItemRepository = feeItemRepository;
        this.linePriceRepository = linePriceRepository;
        this.baoGuanFeeRepository = baoGuanFeeRepository;
        this.clientVehiclePriceRepository = clientVehiclePriceRepository;
        this.vehicleRepository = vehicleRepository;
        this.logService = logService;
        this.snowFlakeFactory = SnowFlakeFactory.getInstance();
    }

    @Override
    public void create(ClientCreateDto clientCreateDto) {
        Assert.hasText(clientCreateDto.getCode(), "客户编号不能为空");
        Assert.hasText(clientCreateDto.getName(), "客户简称不能为空");
        Assert.hasText(clientCreateDto.getFullName(), "客户全称不能为空");
        Assert.hasText(clientCreateDto.getOrganizationId(), "组织机构ID不能为空");
        List<Client> clients = clientRepository.findByOrganizationId(clientCreateDto.getOrganizationId());
        Assert.isTrue(clients.stream().noneMatch(client -> client.getName().equals(clientCreateDto.getName())), String.format("当前机构已经存在相同客户简称【%s】，请更改再保存", clientCreateDto.getName()));
        Client client = new Client();
        BeanUtils.copyProperties(clientCreateDto, client);
        client.setCode(client.getCode().toUpperCase());
        client.setId(snowFlakeFactory.nextId("CL"));
        clientRepository.save(client);
        BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(client.getId());
        if (baoGuanFee == null) {
            baoGuanFee = new BaoGuanFee();
            baoGuanFee.setId(snowFlakeFactory.nextId("BG"));
            baoGuanFee.setBelongId(client.getId());
        }
        baoGuanFee.setHomeFee(clientCreateDto.getHomeFee());
        baoGuanFee.setSheetFee(clientCreateDto.getSheetFee());
        baoGuanFee.setCurrency(clientCreateDto.getCurrency());
        baoGuanFee.setSheetCurrency(clientCreateDto.getSheetCurrency());
        baoGuanFeeRepository.save(baoGuanFee);

        Contract contract = new Contract();
        BeanUtils.copyProperties(clientCreateDto.getContract(), contract);
        contract.setId(snowFlakeFactory.nextId("CT"));
        contract.setBelongId(client.getId());
        contractRepository.save(contract);
        rateRepository.deleteAllByBelongId(client.getId());
        if (clientCreateDto.getRates() != null && clientCreateDto.getRates().size() > 0) {
            List<ExchangeRate> rates = new ArrayList<>();
            clientCreateDto.getRates().forEach(rate -> {
                ExchangeRate saveRate = new ExchangeRate();
                BeanUtils.copyProperties(rate, saveRate);
                saveRate.setId(snowFlakeFactory.nextId("RA"));
                saveRate.setBelongId(client.getId());
                rates.add(saveRate);
            });
            rateRepository.save(rates);
        }
        if (clientCreateDto.getFees() != null && clientCreateDto.getFees().size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            clientCreateDto.getFees().forEach(feeDto -> {
                OrderFee orderFee = new OrderFee();
                orderFee.setFeeName(feeDto.getFeeName());
                orderFee.setFeeCount(feeDto.getFeeCount());
                orderFee.setCurrency(feeDto.getCurrency());
                orderFee.setOrderId(client.getId());
                orderFee.setType(TypeStringUtils.feeInType);
                orderFee.setId(snowFlakeFactory.nextId("OF"));
                fees.add(orderFee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(feeDto.getFeeName().trim());
                if (feeItem == null) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(feeDto.getFeeName().trim());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }

        // 保存车型派送费
        clientVehiclePriceRepository.deleteByBelongId(client.getId());
        List<ClientVehiclePriceDto> vehiclePrices = clientCreateDto.getVehiclePrices();
        if (vehiclePrices != null && vehiclePrices.size() > 0) {
            for (ClientVehiclePriceDto vehiclePrice : vehiclePrices) {
                ClientVehiclePrice clientVehiclePrice = new ClientVehiclePrice();
                clientVehiclePrice.setBelongId(client.getId());
                clientVehiclePrice.setId(snowFlakeFactory.nextId("VP"));
                clientVehiclePrice.setName(vehiclePrice.getName());
                clientVehiclePrice.setAmount(vehiclePrice.getAmount());
                clientVehiclePrice.setUserName(vehiclePrice.getUserName());
                clientVehiclePriceRepository.save(clientVehiclePrice);
            }
        }

        // 保存线路费用
        if (clientCreateDto.getLinePriceImportDtoList() != null && clientCreateDto.getLinePriceImportDtoList().size() > 0) {
            linePriceService.batchCreate(clientCreateDto.getLinePriceImportDtoList(), client.getId(), clientCreateDto.getOpId(), clientCreateDto.getOrganizationId(), "应收");
        }
        User user = userRepository.findById(clientCreateDto.getOpId());
        LogCreateDto createDto = new LogCreateDto(user.getId(), user.getNickName(), "新增客户", client.getName());
        logService.create(createDto);
    }

    @Override
    public void update(ClientUpdateDto updateDto) {
        Assert.hasText(updateDto.getCode(), "客户编号不能为空");
        Assert.hasText(updateDto.getName(), "客户简称不能为空");
        Assert.hasText(updateDto.getFullName(), "客户全称不能为空");
        List<Client> clients = clientRepository.findByOrganizationId(updateDto.getOrganizationId());
        Assert.isTrue(clients.stream().noneMatch(client -> !client.getId().equals(updateDto.getId()) && client.getName().equals(updateDto.getName())), String.format("当前机构已经存在相同客户简称【%s】，请更改再保存", updateDto.getName()));
        Client client = clientRepository.findById(updateDto.getId());
        BeanUtils.copyProperties(updateDto, client, "id");
        client.setCode(client.getCode().toUpperCase());
        clientRepository.save(client);

        BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(client.getId());
        if (baoGuanFee == null) {
            baoGuanFee = new BaoGuanFee();
            baoGuanFee.setId(snowFlakeFactory.nextId("BG"));
            baoGuanFee.setBelongId(client.getId());
        }
        baoGuanFee.setHomeFee(updateDto.getHomeFee());
        baoGuanFee.setSheetFee(updateDto.getSheetFee());
        baoGuanFee.setCurrency(updateDto.getCurrency());
        baoGuanFee.setSheetCurrency(updateDto.getSheetCurrency());
        baoGuanFeeRepository.save(baoGuanFee);

        Contract contract = contractRepository.findByBelongId(client.getId());
        BeanUtils.copyProperties(updateDto.getContract(), contract, "id");
        contractRepository.save(contract);
        rateRepository.deleteAllByBelongId(client.getId());
        if (updateDto.getRates() != null && updateDto.getRates().size() > 0) {
            List<ExchangeRate> rates = new ArrayList<>();
            updateDto.getRates().forEach(rate -> {
                ExchangeRate saveRate = new ExchangeRate();
                BeanUtils.copyProperties(rate, saveRate);
                saveRate.setId(snowFlakeFactory.nextId("RA"));
                saveRate.setBelongId(client.getId());
                rates.add(saveRate);
            });
            rateRepository.save(rates);
        }
        orderFeeRepository.deleteByOrderId(client.getId());
        if (updateDto.getFees() != null && updateDto.getFees().size() > 0) {
            List<OrderFee> fees = new ArrayList<>();
            updateDto.getFees().forEach(feeDto -> {
                OrderFee orderFee = new OrderFee();
                orderFee.setFeeName(feeDto.getFeeName());
                orderFee.setFeeCount(feeDto.getFeeCount());
                orderFee.setCurrency(feeDto.getCurrency());
                orderFee.setOrderId(client.getId());
                orderFee.setType(TypeStringUtils.feeInType);
                orderFee.setId(snowFlakeFactory.nextId("OF"));
                fees.add(orderFee);
                // 检查费用科目是否存在，如果不存在则新增
                FeeItem feeItem = feeItemRepository.findByName(feeDto.getFeeName().trim());
                if (feeItem == null) {
                    feeItem = new FeeItem();
                    feeItem.setId(snowFlakeFactory.nextId("FI"));
                    feeItem.setName(feeDto.getFeeName().trim());
                    feeItemRepository.save(feeItem);
                }
            });
            orderFeeRepository.save(fees);
        }
        // 保存车型派送费
        List<ClientVehiclePriceDto> vehiclePrices =
                updateDto.getVehiclePrices().stream().filter(dto -> !dto.getId().contains("VP") && StringUtils.hasText(dto.getName())).collect(Collectors.toList());
        if (vehiclePrices.size() > 0) {
            for (ClientVehiclePriceDto vehiclePrice : vehiclePrices) {
                ClientVehiclePrice clientVehiclePrice = new ClientVehiclePrice();
                clientVehiclePrice.setBelongId(client.getId());
                clientVehiclePrice.setId(snowFlakeFactory.nextId("VP"));
                clientVehiclePrice.setName(vehiclePrice.getName());
                clientVehiclePrice.setAmount(vehiclePrice.getAmount());
                clientVehiclePrice.setStartPlace(vehiclePrice.getStartPlace());
                clientVehiclePrice.setEndPlace(vehiclePrice.getEndPlace());
                clientVehiclePrice.setUserName(vehiclePrice.getUserName());
                clientVehiclePriceRepository.save(clientVehiclePrice);
            }
        }
        // 更新原有的
        vehiclePrices =
                updateDto.getVehiclePrices().stream().filter(dto -> dto.getId().contains("VP") && StringUtils.hasText(dto.getName())).collect(Collectors.toList());
        if(vehiclePrices.size() > 0){
            for (ClientVehiclePriceDto dto : vehiclePrices) {
                ClientVehiclePrice vehiclePrice = clientVehiclePriceRepository.getOne(dto.getId());
                vehiclePrice.setName(dto.getName());
                vehiclePrice.setStartPlace(dto.getStartPlace());
                vehiclePrice.setEndPlace(dto.getEndPlace());
                vehiclePrice.setAmount(dto.getAmount());
                clientVehiclePriceRepository.save(vehiclePrice);
            }
        }
        User user = userRepository.findById(updateDto.getOpId());
        LogCreateDto createDto = new LogCreateDto(user.getId(), user.getNickName(), "修改客户", client.getName());
        logService.create(createDto);
    }

    @Override
    public PageResult<ClientDto> query(ClientQueryDto params) {
        List<Organization> organizations = organizationService.getAll();
        Specification<Client> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Predicate organizationId = criteriaBuilder.equal(root.get("organizationId"), params.getCurrentOrgId());
            predicates.add(organizationId);
            if (!StringUtils.isEmpty(params.getCode())) {
                Predicate site = criteriaBuilder.like(root.get("code"), "%" + params.getCode().trim() + "%");
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(params.getFullName())) {
                Predicate site = criteriaBuilder.like(root.get("fullName"), "%" + params.getFullName().trim() + "%");
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(params.getName())) {
                Predicate site = criteriaBuilder.like(root.get("name"), "%" + params.getName().trim() + "%");
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(params.getLicence())) {
                Predicate site = criteriaBuilder.like(root.get("licence"), "%" + params.getLicence().trim() + "%");
                predicates.add(site);
            }
            if (params.getCreateTimeStart() != null) {
                Predicate timeStart = criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), params.getCreateTimeStart().atStartOfDay());
                predicates.add(timeStart);
            }
            if (params.getCreateTimeEnd() != null) {
                Predicate timeEnd = criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), params.getCreateTimeEnd().plusDays(1));
                predicates.add(timeEnd);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        Pageable pageable = new PageRequest(params.getPage() - 1, params.getPageSize(), sort);
        Page<Client> details = clientRepository.findAll(specification, pageable);
        List<Client> clients = details.getContent();
        List<String> clientIds = clients.stream().map(Client::getId).collect(Collectors.toList());
        List<ClientDto> clientDtos = new ArrayList<>();
        List<Contract> contracts = contractRepository.findByBelongIdIn(clientIds);
        if (clients.size() > 0) {
            clients.forEach(client -> {
                ClientDto dto = new ClientDto();
                BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(client.getId());
                BeanUtils.copyProperties(client, dto);
                if (baoGuanFee != null) {
                    dto.setHomeFee(baoGuanFee.getHomeFee());
                    dto.setSheetFee(baoGuanFee.getSheetFee());
                    dto.setCurrency(baoGuanFee.getCurrency());
                    dto.setSheetCurrency(baoGuanFee.getSheetCurrency());
                }
                organizations.stream().filter(organization -> organization.getId().equals(client.getOrganizationId())).findFirst().ifPresent(organization -> dto.setTaiTou(organization.getName()));
                contracts.stream().filter(contract -> contract.getBelongId().equals(client.getId())).findFirst().ifPresent(contract -> {
                    BeanUtils.copyProperties(contract, dto, "id");
                });
                clientDtos.add(dto);
            });
        }
        return PageResult.of(clientDtos, params.getPage(), params.getPageSize(), details.getTotalElements());
    }

    @Override
    public void delete(String id, String userId) {
        Client client = clientRepository.findById(id);
        clientRepository.delete(client);
        contractRepository.deleteByBelongId(id);
        rateRepository.deleteAllByBelongId(id);
        User user = userRepository.findById(userId);
        LogCreateDto createDto = new LogCreateDto(user.getId(), user.getNickName(), "删除客户", client.getName());
        logService.create(createDto);
    }

    @Override
    public ClientDetailDto getById(String id) {
        Client client = clientRepository.findById(id);
        ClientDetailDto clientDetailDto = new ClientDetailDto();
        BeanUtils.copyProperties(client, clientDetailDto);
        Contract contract = contractRepository.findByBelongId(id);
        ClientDetailDto.ContractDto contractDto = new ClientDetailDto.ContractDto();
        BeanUtils.copyProperties(contract, contractDto);
        clientDetailDto.setContract(contractDto);
        List<ExchangeRate> rates = rateRepository.findByBelongId(id);
        List<ClientDetailDto.ExchangeRateDto> rateDtos = new ArrayList<>();
        if (rates.size() > 0) {
            rates.forEach(exchangeRate -> {
                ClientDetailDto.ExchangeRateDto dto = new ClientDetailDto.ExchangeRateDto();
                BeanUtils.copyProperties(exchangeRate, dto);
                rateDtos.add(dto);
            });
            clientDetailDto.setRates(rateDtos);
        }
        List<LinePrice> linePrices = linePriceRepository.findByBelongId(id);
        List<ClientDetailDto.LinePrice> dtos = new ArrayList<>();
        linePrices.forEach(linePrice -> {
            ClientDetailDto.LinePrice dto = new ClientDetailDto.LinePrice();
            BeanUtils.copyProperties(linePrice, dto);
            dtos.add(dto);
        });
        clientDetailDto.setLinePrices(dtos);
        // 车型派送费
        List<Vehicle> vehicles = vehicleRepository.findAll();
        List<ClientVehiclePrice> vehiclePrices = clientVehiclePriceRepository.findByBelongId(id);
        List<ClientVehiclePriceDto> vehiclePriceDtos = new ArrayList<>();
        for (Vehicle vehicle : vehicles) {
            ClientVehiclePriceDto dto = new ClientVehiclePriceDto();
            dto.setName(vehicle.getName());
            vehiclePrices.stream().filter(clientVehiclePrice -> clientVehiclePrice.getName().equals(vehicle.getName())).findFirst().ifPresent(clientVehiclePrice -> {
                dto.setAmount(clientVehiclePrice.getAmount());
                dto.setStartPlace(clientVehiclePrice.getStartPlace());
                dto.setEndPlace(clientVehiclePrice.getEndPlace());
            });
            vehiclePriceDtos.add(dto);
        }
        clientDetailDto.setVehiclePrices(vehiclePriceDtos);
        // 报关费
        BaoGuanFee baoGuanFee = baoGuanFeeRepository.findByBelongId(id);
        clientDetailDto.setBaoGuanFee(baoGuanFee);
        return clientDetailDto;
    }

    @Override
    public List<ClientDto> getAll() {
        List<ClientDto> clientDtos = new ArrayList<>();
        List<Client> clients = clientRepository.findAll();
        List<String> orgIds = clients.stream().map(Client::getOrganizationId).collect(Collectors.toList());
        List<Organization> organizations = organizationService.getAllByIds(orgIds);
        clients.forEach(client -> {
            ClientDto dto = new ClientDto();
            BeanUtils.copyProperties(client, dto);
            organizations.stream().filter(organization -> organization.getId().equals(client.getOrganizationId())).findFirst().ifPresent(organization -> dto.setOrganizationName(organization.getName()));
            clientDtos.add(dto);
        });
        return clientDtos;
    }

    @Override
    public List<LinePrice> getLinesByClientId(String clientId, boolean flag) {
        List<LinePrice> linePrices = linePriceRepository.findByBelongId(clientId);
        if (flag) {
            linePrices = linePrices.stream().filter(linePrice -> "综合物流".equals(linePrice.getBusinessType()) || "仓储".equals(linePrice.getBusinessType())).collect(Collectors.toList());
        }
        return linePrices;
    }

    @Override
    public List<OrderFee> getByClientId(String clientId) {
        return orderFeeRepository.findByOrderId(clientId);
    }

    @Override
    public List<ClientVehiclePriceDto> getVehiclePrices(VehicleFeeQueryDto params) {
        List<ClientVehiclePriceDto> dtos = new ArrayList<>();
        Specification<ClientVehiclePrice> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Predicate belongId = criteriaBuilder.equal(root.get("belongId"), params.getOwnerId());
            predicates.add(belongId);
            if (!StringUtils.isEmpty(params.getName())) {
                Predicate name = criteriaBuilder.like(root.get("name"), "%" + params.getName().trim() + "%");
                predicates.add(name);
            }
            if (!StringUtils.isEmpty(params.getStartPlace())) {
                Predicate startPlace = criteriaBuilder.like(root.get("startPlace"), "%" + params.getStartPlace().trim() +
                        "%");
                predicates.add(startPlace);
            }
            if (!StringUtils.isEmpty(params.getEndPlace())) {
                Predicate endPlace = criteriaBuilder.like(root.get("endPlace"), "%" + params.getEndPlace().trim() + "%");
                predicates.add(endPlace);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        Sort sort = new Sort(Sort.Direction.ASC, "name");
        List<ClientVehiclePrice> prices = clientVehiclePriceRepository.findAll(specification, sort);
        for (ClientVehiclePrice vehiclePrice : prices) {
            ClientVehiclePriceDto dto = new ClientVehiclePriceDto();
            BeanUtils.copyProperties(vehiclePrice, dto);
            dtos.add(dto);
        }
        return dtos;
    }

    @Override
    public void batchCreate(List<ClientImportDto> importDatas, String opId) {
        User user = userRepository.findById(opId);
        List<Organization> organizations = organizationService.getAll();
        List<Client> clients = clientRepository.findAll();
        for (ClientImportDto importData : importDatas) {
            boolean noneMatch = clients.stream().noneMatch(client -> client.getCode().equals(importData.getCode()));
            Assert.isTrue(noneMatch, "系统存在客户编码[" + importData.getCode() + "]");
            noneMatch = clients.stream().noneMatch(client -> client.getName().equals(importData.getName()));
            Assert.isTrue(noneMatch, "系统存在客户简称[" + importData.getName() + "]");
            if (StringUtils.hasText(importData.getTaiTou())) {
                boolean anyMatch = organizations.stream().anyMatch(organization -> organization.getName().equals(importData.getTaiTou()));
                Assert.isTrue(anyMatch, "没有找到机构抬头为[" + importData.getTaiTou() + "]的记录");
            }
        }
        for (ClientImportDto importData : importDatas) {
            ClientCreateDto createDto = new ClientCreateDto();
            BeanUtils.copyProperties(importData, createDto);
            ClientCreateDto.ContractDto contract = new ClientCreateDto.ContractDto();
            BeanUtils.copyProperties(importData, contract);
            if (importData.getSignedDate() != null) {
                Instant instant = importData.getSignedDate().toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                contract.setSignedDate(instant.atZone(zoneId).toLocalDate());
            }
            if (importData.getExpiresDate() != null) {
                Instant instant = importData.getExpiresDate().toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                contract.setExpiresDate(instant.atZone(zoneId).toLocalDate());
            }
            if (importData.getRemindDate() != null) {
                Instant instant = importData.getRemindDate().toInstant();
                ZoneId zoneId = ZoneId.systemDefault();
                // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime
                contract.setRemindDate(instant.atZone(zoneId).toLocalDate());
            }
            createDto.setContract(contract);
            organizations.stream().filter(organization -> organization.getName().equals(importData.getTaiTou())).findFirst().ifPresent(organization -> createDto.setOrganizationId(organization.getId()));
            if (StringUtils.isEmpty(createDto.getOrganizationId())) {
                createDto.setOrganizationId(user.getOrganizationId());
            }
            createDto.setOpId(opId);
            this.create(createDto);
        }
    }

    @Override
    public List<ClientDto> getClientListByOrgId(String orgId) {
        List<ClientDto> clientDtos = new ArrayList<>();
        List<Client> clients = clientRepository.findByOrganizationIdIn(Collections.singletonList(orgId));
        clients.forEach(client -> {
            ClientDto dto = new ClientDto();
            BeanUtils.copyProperties(client, dto);
            clientDtos.add(dto);
        });
        return clientDtos;
    }

    @Override
    public void batchCreateVehicleList(List<CarrierVehicleFeeImportDto> importDatas, String belongId) {
        List<Vehicle> vehicles = vehicleRepository.findAll();
        List<ClientVehiclePrice> historyList = clientVehiclePriceRepository.findByBelongId(belongId);
        Map<String, List<CarrierVehicleFeeImportDto>> listMap = importDatas.stream().collect(Collectors.groupingBy(importData -> importData.getName() + importData.getStartPlace() + importData.getEndPlace()));
        listMap.forEach((key, dataList) -> {
            CarrierVehicleFeeImportDto importData = dataList.get(0);
            boolean hasVehicleRecord = vehicles.stream().anyMatch(vehicle -> vehicle.getName().equals(importData.getName()));
            if (!hasVehicleRecord) {
                Vehicle vehicle = new Vehicle();
                vehicle.setId(snowFlakeFactory.nextId("VC"));
                vehicle.setName(importData.getName());
                vehicleRepository.save(vehicles);
            }
            Optional<ClientVehiclePrice> optional = historyList.stream().filter(record -> record.getName().equals(importData.getName()) && record.getStartPlace().equals(importData.getStartPlace()) && record.getEndPlace().equals(importData.getEndPlace())).findFirst();
            if (optional.isPresent()) {
                ClientVehiclePrice save = optional.get();
                save.setAmount(importData.getAmount());
                clientVehiclePriceRepository.save(save);
                return;
            }
            ClientVehiclePrice clientVehiclePrice = new ClientVehiclePrice();
            clientVehiclePrice.setBelongId(belongId);
            clientVehiclePrice.setId(snowFlakeFactory.nextId("VP"));
            clientVehiclePrice.setName(importData.getName());
            if (importData.getAmount() != null) {
                clientVehiclePrice.setAmount(importData.getAmount());
            } else {
                clientVehiclePrice.setAmount(0d);
            }
            clientVehiclePrice.setStartPlace(importData.getStartPlace());
            clientVehiclePrice.setEndPlace(importData.getEndPlace());
            clientVehiclePriceRepository.save(clientVehiclePrice);
        });
    }

    @Override
    public List<LinePrice> getLines(LineQueryDto lineQueryDto) {
        Specification<LinePrice> specification = ((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (!StringUtils.isEmpty(lineQueryDto.getClientId())) {
                Predicate site = criteriaBuilder.like(root.get("belongId"), lineQueryDto.getClientId());
                predicates.add(site);
            }
            if (!StringUtils.isEmpty(lineQueryDto.getBusinessCode())) {
                Predicate site = criteriaBuilder.like(root.get("businessType"), lineQueryDto.getBusinessCode());
                predicates.add(site);
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        });
        return linePriceRepository.findAll(specification);
    }
}
